package com.component.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.component.domain.MLog;
import com.component.domain.MSearchLog;
import com.component.domain.Note;
import com.component.domain.vo.NoteStatusVo;
import com.component.enumitem.NoteStatusEnum;
import com.component.mapper.NoteMapper;
import com.component.service.MLogService;
import com.component.service.MSearchLogService;
import com.component.service.NoteService;
import com.system.security.SecurityUtil;
import com.system.security.domain.SelfUserEntity;
import com.system.util.EnumToListConverter;
import com.system.util.IPUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.annotations.CacheNamespace;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author Xiongx
 * @version 1.0
 * @date 2021/6/6 0:19
 * @since JDK 1.8
 */
@Service
@CacheConfig(cacheNames = "NoteServiceImpl")
public class NoteServiceImpl extends ServiceImpl<NoteMapper, Note> implements NoteService {

    @Autowired
    private MSearchLogService mSearchLogService;

    @Override
    public Integer getNoteCountByChannelId(Serializable id) {
        LambdaQueryWrapper<Note> lambdaQueryWrapper=new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Note::getChannelId,id);
        Integer count=this.baseMapper.selectCount(lambdaQueryWrapper);
        return count;
    }

    @Cacheable(cacheNames = "note",key = "#id")
    @Override
    public Note getById(Serializable id) {
        return super.getById(id);
    }


    @Caching(
            evict = {
                    @CacheEvict(value = "note", key = "#entity.id"),
            }
    )
    @Override
    public boolean updateById(Note entity) {
        return super.updateById(entity);
    }

    @Override
    public Integer updateNoteChannel(String channelId, List<String> ids) {
        UpdateWrapper<Note> wrapper = new UpdateWrapper<>();
        wrapper.set("channelid", channelId);
        wrapper.in("id", ids);
        this.baseMapper.update(null, wrapper);
        return 0;
    }

    @Override
    public IPage<Note> notePageListByKeyWord(Integer page, Integer size, String channelId, String keyword, Map<String, Object> query,Boolean isPri) {
        LambdaQueryWrapper<Note> noteLambdaQueryWrapper=new LambdaQueryWrapper<>();
        noteLambdaQueryWrapper.select(Note::getId,Note::getTitle,Note::getTag,Note::getCreateTime,Note::getViewnum,Note::getChannelId,Note::getIsprivate,Note::getDatatype);
        noteLambdaQueryWrapperCommon(noteLambdaQueryWrapper,isPri);
        if (StringUtils.isNotBlank(keyword) && !"''".equals(keyword)) {
            mSearchLogService.addKeyword(keyword);
            noteLambdaQueryWrapper.and(wrapper->{
                wrapper.like(Note::getTitle,keyword);
                wrapper.or().like(Note::getTag,keyword);
            });
        }
        if (StringUtils.isNotBlank(channelId)) {
            noteLambdaQueryWrapper.eq(Note::getChannelId,channelId);
        }
        if (query != null) {
            if (query.containsKey("tag")) {
                String tag = query.get("tag").toString();
                noteLambdaQueryWrapper.like(Note::getTag,tag);
            }
            if (query.containsKey("title")) {
                String title = query.get("title").toString();
                noteLambdaQueryWrapper.like(Note::getTitle,title);
            }
            if (query.containsKey("date")) {
                String date = query.get("date").toString();
                noteLambdaQueryWrapper.lt(Note::getCreateTime,date);
            }
            if(query.containsKey("status")){
                String status = query.get("status").toString();
                noteLambdaQueryWrapper.eq(Note::getStatus,status);
            }
        }
        if (StringUtils.isNotBlank(keyword) && !"".equals(keyword)) {
            noteLambdaQueryWrapper.orderByDesc(Note::getViewnum,Note::getCreateTime);
        } else {
            noteLambdaQueryWrapper.orderByDesc(Note::getCreateTime);
        }
        IPage<Note> noteIPage = super.page(new Page(page, size), noteLambdaQueryWrapper);
        return noteIPage;
    }



    @Autowired
    private MLogService mLogService;

    @Override
    public Integer addOneNoteReadCountByNid(Integer nid) {
        Integer code = 0;
        Note note = getById(nid);
        if (note != null) {
            note.setViewnum(note.getViewnum() + 1);
            code = super.getBaseMapper().updateById(note);
        }
        HttpServletRequest req = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        HttpServletResponse resp = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        String ip = IPUtils.getIpAddr(req);
        SelfUserEntity userEntity = SecurityUtil.getSelfUserEntity();
        MLog mLog = new MLog();
        mLog.setLogname("内容访问");
        mLog.setCreatedate(new Date());
        mLog.setIp(ip);
        mLog.setUrl(note.getContentUrl());
        mLog.setNoteId(note.getId().toString());
        mLog.setTitle(note.getTitle());
        if (userEntity != null) {
            mLog.setUid(userEntity.getUserId().toString());
            mLog.setRealname(userEntity.getUsername());
            mLog.setUsername(userEntity.getUsername());
        } else {
            mLog.setRealname("匿名用户");
            mLog.setUsername("匿名用户");
        }
        mLogService.save(mLog);
        return code;
    }

    @Override
    public IPage<Note> pageIPage(Integer pageNum, Integer pageSize, String channelId, String tag, String title, Date beforeDate) {
        LambdaQueryWrapper<Note> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        noteLambdaQueryWrapperCommon(lambdaQueryWrapper,false);
        if (StringUtils.isNotBlank(channelId)) {
            lambdaQueryWrapper.eq(Note::getChannelId, channelId);
        }
        if (StringUtils.isNotBlank(tag)) {
            lambdaQueryWrapper.like(Note::getTag, tag);
        }
        if (StringUtils.isNotBlank(title)) {
            lambdaQueryWrapper.like(Note::getTitle, title);
        }
        if (beforeDate != null) {
            lambdaQueryWrapper.gt(Note::getCreateTime, beforeDate);
        }

        lambdaQueryWrapper.orderByDesc(Note::getCreateTime);
        IPage<Note> page = super.page(new Page(pageNum, pageSize), lambdaQueryWrapper);
        return page;
    }

    @Override
    public List<Note> channelList(String channelId, int total) {
        LambdaQueryWrapper<Note> queryWrapper = new LambdaQueryWrapper<>();
        noteLambdaQueryWrapperCommon(queryWrapper,false);
        if (StringUtils.isNotBlank(channelId)) {
            queryWrapper.eq(Note::getChannelId, channelId);
        }
        if (total > 0) {
            queryWrapper.last(" limit " + total);
        }
        List<Note> noteList = super.baseMapper.selectList(queryWrapper);
        return noteList;
    }

    @Override
    public List<Note> getChangeNoteList() {
        LambdaQueryWrapper<Note> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Note::getChangeStatus, 0);
        noteLambdaQueryWrapperCommon(queryWrapper,false);
        List<Note> noteList = this.baseMapper.selectList(queryWrapper);
        return noteList;
    }

    @Override
    public Boolean setStatus(NoteStatusVo noteStatusVo) {
        Note note=this.getById(noteStatusVo.getId());
        if(note==null){
            return false;
        }
        NoteStatusEnum[] noteStatusEnums=NoteStatusEnum.values();
        List<Map<String,Object>>maps= EnumToListConverter.convert(noteStatusEnums,"status","statusName");
        boolean isExist=maps.stream().anyMatch(e->e.get("status").toString().equals(String.valueOf(noteStatusVo.getStatus())));
        if(isExist){
            note.setStatus(noteStatusVo.getStatus().toString());
            this.updateById(note);
            return true;
        }
        return false;
    }

    @Override
    public List<Map<String, Object>> searchKeywordList(String keyword) {
        if(StringUtils.isNotBlank(keyword)){
            LambdaQueryWrapper<Note> lambdaQueryWrapper=new LambdaQueryWrapper<>();
            lambdaQueryWrapper.select(Note::getTitle);
            lambdaQueryWrapper.eq(Note::getIsprivate,false);
            if(StringUtils.isNotBlank(keyword)){
                lambdaQueryWrapper.like(Note::getTitle,keyword);
            }
            lambdaQueryWrapper.orderByDesc(Note::getViewnum);
            lambdaQueryWrapper.orderByDesc(Note::getCreateTime);
            lambdaQueryWrapper.last(" limit 15");
            List<Map<String,Object>> mapList=this.baseMapper.selectMaps(lambdaQueryWrapper);
            if(mapList!=null && mapList.size() > 0) {
                for (Map<String, Object> map : mapList) {
                    String keyword1=(String) map.get("title");
                    map.put("value",keyword1);
                }
            }
            return mapList;
        }else {
            LambdaQueryWrapper<MSearchLog> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.select(MSearchLog::getKeyword);
            List<Map<String,Object>> mapList=mSearchLogService.history();
            if(mapList!=null && mapList.size() > 0){
                for (Map<String, Object> map : mapList) {
                    String keyword1=(String) map.get("keyword");
                    map.put("value",keyword1);
                }
            }
            return mapList;
        }
    }


    public void noteLambdaQueryWrapperCommon(LambdaQueryWrapper<Note> queryWrapper,boolean ispri){
        if(queryWrapper!=null){
            SelfUserEntity userEntity=SecurityUtil.getSelfUserEntity();
            if(userEntity==null || !ispri){
                queryWrapper.eq(Note::getIsprivate,false);
            }else {
                //查询自己的
                queryWrapper.and(wrapper ->{
                   // wrapper.eq(Note::getIsprivate,false);
                    wrapper.or(query->{
                        query.eq(Note::getIsprivate,true)
                                .eq(Note::getUserid,userEntity.getUserId().toString());
                    });
                });
            }
        }
    }


}
